<?php

namespace App\Controller\Admin;

use App\Constants\ErrorCode;
use App\Middleware\AdminMiddleware;
use App\Model\AdminAuthGroup;
use App\Model\AdminAuthGroupAccess;
use App\Model\AdminAuthRule;
use App\Model\AdminMenu;
use App\Service\ToolService;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\PostMapping;
use function Hyperf\Config\config;

#[Controller(prefix: '/admin/Auth'), Middleware(AdminMiddleware::class)]
class AuthController extends BaseController {
    /**
     * 获取权限组列表
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'index')]
    public function index(): array {
        $limit    = $this->request->query('size', config('apiadmin.admin_list_default'));
        $keywords = $this->request->query('keywords', '');
        $status   = $this->request->query('status', '');

        $obj = AdminAuthGroup::query();
        if (strlen($status)) {
            $obj = $obj->where('status', $status);
        }
        if ($keywords) {
            $obj = $obj->where('name', 'like', "%{$keywords}%");
        }

        $listObj = $obj->orderByDesc('id')->paginate($limit);

        return $this->buildSuccess([
            'list'  => $listObj->items(),
            'count' => $listObj->total()
        ]);
    }

    /**
     * 获取全部已开放的可选组
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'getGroups')]
    public function getGroups(): array {
        $listInfo = AdminAuthGroup::query()->where('status', 1)->orderByDesc('id')->get();
        $count    = count($listInfo);
        $listInfo = ToolService::buildArrFromObj($listInfo);

        return $this->buildSuccess([
            'list'  => $listInfo,
            'count' => $count
        ]);
    }

    /**
     * 获取组所在权限列表
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'getRuleList')]
    public function getRuleList(): array {
        $groupId = $this->request->query('group_id', 0);

        $list = AdminMenu::query()->orderBy('sort')->get();
        $list = ToolService::buildArrFromObj($list);
        $list = ToolService::listToTree($list);

        $rules = [];
        if ($groupId) {
            $rules = AdminAuthRule::query()->where('group_id', $groupId)->get();
            $rules = ToolService::buildArrFromObj($rules);
            $rules = array_column($rules, 'url');
        }
        $newList = $this->buildList($list);

        return $this->buildSuccess([
            'list'  => $newList,
            'rules' => $rules
        ]);
    }

    /**
     * 构建适用前端的权限数据
     * @param $list
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    private function buildList($list): array {
        $newList = [];
        foreach ($list as $key => $value) {
            $newList[$key]['title'] = $value['title'];
            if (empty($value['url'])) {
                $newList[$key]['key'] = (string)$value['id'];
            } else {
                $newList[$key]['key'] = $value['url'];
            }
            if (isset($value['children'])) {
                $newList[$key]['children'] = $this->buildList($value['children']);
            }
        }
        return $newList;
    }

    /**
     * 新增组
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[PostMapping(path: 'add')]
    public function add(): array {
        $res = AdminAuthGroup::insert([
            'name'        => $this->request->post('name', ''),
            'description' => $this->request->post('description', '')
        ]);
        if ($res === false) {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR);
        }

        return $this->buildSuccess();
    }

    /**
     * 权限组状态编辑
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'changeStatus')]
    public function changeStatus(): array {
        $id     = $this->request->query('id', '');
        $status = $this->request->query('status', '');
        $resObj = AdminAuthGroup::find($id);
        if ($resObj) {
            $resObj->status = $status;
            $resObj->save();
        } else {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR);
        }

        return $this->buildSuccess();
    }

    /**
     * 编辑用户
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[PostMapping(path: 'edit')]
    public function edit(): array {
        $id     = $this->request->post('id', '');
        $resObj = AdminAuthGroup::find($id);
        if ($resObj) {
            $resObj->name        = $this->request->post('name', '');
            $resObj->description = $this->request->post('description', '');
            $resObj->save();
        } else {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR);
        }

        return $this->buildSuccess();
    }

    /**
     * 删除组
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'del')]
    public function del(): array {
        $id = $this->request->query('id', '');
        if (!$id) {
            return $this->buildFailed(ErrorCode::EMPTY_PARAMS, '缺少必要参数');
        }

        $listInfo = AdminAuthGroupAccess::query()->whereRaw('FIND_IN_SET(?, group_id)', [$id])->get();
        if ($listInfo) {
            foreach ($listInfo as $value) {
                $oldGroupArr = explode(',', $value->group_id);
                $key         = array_search($id, $oldGroupArr);
                unset($oldGroupArr[$key]);
                $newData         = implode(',', $oldGroupArr);
                $value->group_id = $newData;
                $value->save();
            }
        }
        AdminAuthGroup::destroy($id);
        AdminAuthRule::query()->where('group_id', $id)->delete();

        return $this->buildSuccess();
    }

    /**
     * 从指定组中删除指定用户
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'delMember')]
    public function delMember(): array {
        $gid = $this->request->query('gid', 0);
        $uid = $this->request->query('uid', 0);
        if (!$gid || !$uid) {
            return $this->buildFailed(ErrorCode::EMPTY_PARAMS, '缺少必要参数');
        }
        $oldInfo = AdminAuthGroupAccess::query()->where('uid', $uid)->first();
        if ($oldInfo) {
            $oldGroupArr = explode(',', $oldInfo->group_id);
            $key         = array_search($gid, $oldGroupArr);
            unset($oldGroupArr[$key]);
            $oldInfo->group_id = implode(',', $oldGroupArr);
            $oldInfo->save();
        } else {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR);
        }

        return $this->buildSuccess();
    }

    /**
     * 编辑权限细节
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[PostMapping(path: 'editRule')]
    public function editRule(): array {
        $id    = $this->request->post('id', 0);
        $rules = $this->request->post('rules', []);
        if (is_array($rules)) {
            $needAdd = [];
            $has     = AdminAuthRule::query()->where('group_id', $id)->get();
            $has     = ToolService::buildArrFromObj($has);
            $hasRule = array_column($has, 'url');
            $needDel = array_flip($hasRule);
            foreach ($rules as $key => $value) {
                if (!empty($value)) {
                    if (!in_array($value, $hasRule)) {
                        $data['url']      = $value;
                        $data['group_id'] = $id;
                        $needAdd[]        = $data;
                    } else {
                        unset($needDel[$value]);
                    }
                }
            }
            if (count($needAdd)) {
                AdminAuthRule::insert($needAdd);
            }
            if (count($needDel)) {
                $urlArr = array_keys($needDel);
                AdminAuthRule::query()->whereIn('url', $urlArr)->where('group_id', $id)->delete();
            }
        }

        return $this->buildSuccess();
    }
}
